/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gameheart.client.logic;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;

/**
 *
 * @author win7
 */
public class MainGame extends JFrame implements WindowListener, Runnable {

    public MainGame() {
        running = true;
        Container c = getContentPane();
        c.setLayout(new BorderLayout());
        addWindowListener(this);
        pack();
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        this.setTitle("My Game Heart");
        this.setSize(1030, 745);
        this.setLocation(10, 10);
        setResizable(false);
        setVisible(true);
        dbImage = this.createImage(1024, 738);
        if (dbImage == null) {
            System.out.println("dbImage is null");
            return;
        } else {
            g = dbImage.getGraphics();
        }
        this.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                processMouseClickeda(e);
            }
        });
        this.addKeyListener(new KeyAdapter() {

            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                processKeyPressedb(e);
            }
        });
    }

    private void processMouseClickeda(MouseEvent mouseEvent) {
        _currentState.mouseClicked(mouseEvent);

    }

    private void processKeyPressedb(KeyEvent keyEvent) {
        _currentState.keyPressed(keyEvent);

    }
    volatile private boolean _needRepaint = true;
    volatile private boolean _deactived = false;

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        _needRepaint = true;
    }
    volatile public boolean logicChange = true;

    public void windowOpened(WindowEvent e) {
        _needRender = true;
        _needRepaint = true;
    }

    public void windowClosing(WindowEvent e) {
    }

    public void windowClosed(WindowEvent e) {
        _needRender = false;
        _needRepaint = false;
    }

    public void windowIconified(WindowEvent e) {
    }

    public void windowDeiconified(WindowEvent e) {
    }

    public void windowActivated(WindowEvent e) {
        _needRender = true;
        _deactived = false;
    }

    public void windowDeactivated(WindowEvent e) {
        _needRender = false;
        _deactived = true;
    }
    private ClientAdapter _adapter;
    volatile boolean _needRender = true;

    public void run() {
        gameLoop();
    }
    State _currentState = null;
    private long _preTick;
    private long _sleepTime = 0;
    public gameheart.server.GameServerCanvas _server = null;
    private boolean _changeState = true;
    private int nextStateId = GameStateIds.MenuStateId;

    public void ChangeGameState(int gameStateId) {
        _changeState = true;
        nextStateId = gameStateId;
    }
    String _userName = "";

    public State CreateGameState(int gameStateId) {
        State result = null;
        switch (gameStateId) {
            case GameStateIds.JoinStateId: {
                result = new JoinState(this);
                break;
            }
            case GameStateIds.MenuStateId: {
                result = new MenuState(this);
                break;
            }
            case GameStateIds.PlayStateId: {
                result = new PlayCanvas(this, getAdapter());
                break;

            }
            case GameStateIds.WaitUserStateId: {
                result = new WaitUserState(this);
                break;
            }
            case GameStateIds.CreateGameState: {
                result = new CreateGameState(this);
                break;
            }

            case GameStateIds.EndGameState: {
                result = new EndGameState(this);
            }
            break;
        }
    
    return result ;
}
public void gameLoop() {
        _preTick = System.currentTimeMillis();
        while (running) {
            if (_changeState) {
                if (_currentState != null) {
                    _currentState.gameEnd();
                }
                _currentState = CreateGameState(nextStateId);
                _currentState.gameInit();
                _changeState = false;
            }
            _currentState.gameUpdate();
            if (_needRender) {
                _currentState.gameRender(g);
            }
            GameSleep();
            if (!_deactived || _needRepaint) {
                PaintScreen();
                _needRepaint = false;
            }

        }
    }
    private int _minTime = 33;

    private void GameSleep() {
        long nowTick = System.currentTimeMillis();
        long deltaTick = nowTick - _preTick;
        _preTick = nowTick;
        if (deltaTick <= _minTime) {
            _sleepTime = _minTime - deltaTick;
        } else {
            _sleepTime = 0;
        }
        try {
            Thread.sleep(_sleepTime);
        

} catch (InterruptedException ex) {
            Logger.getLogger(MainGame.class  

.getName()).log(Level.SEVERE, null, ex);
        }
    }
    Graphics g;
    private Image dbImage = null;
    boolean running;

    private void PaintScreen() {
        Graphics gp;
        try {
            gp = this.getGraphics();
            if ((gp != null) && (dbImage != null)) {
                gp.drawImage(dbImage, 0, 30, 1024, 738, this);
            }
            Toolkit.getDefaultToolkit().sync();
            gp.dispose();
        } catch (Exception e) {
            System.out.println("Graphics context error: " + e);

        }
    }

    /**
     * @return the _adapter
     */
    public ClientAdapter getAdapter() {
        return _adapter;
    }

    /**
     * @param adapter the _adapter to set
     */
    public void setAdapter(ClientAdapter adapter) {
        this._adapter = adapter;
    }
}
